﻿using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Shapes;
using System.Xml;
using SHomeWorkshop.LunarConcept.Adorners;
using SHomeWorkshop.LunarConcept.Controls;
using SHomeWorkshop.LunarConcept.Enums;
using SHomeWorkshop.LunarConcept.Tools;
using SHomeWorkshop.LunarConcept.Widgets.Interfaces;
using System.Collections.Generic;
using SHomeWorkshop.LunarMind;

namespace SHomeWorkshop.LunarConcept.Widgets
{
    /// <summary>
    /// 创建时间：2012年1月20日
    /// 创建者：  杨震宇
    /// 
    /// 主要用途：提供一个菱形部件。
    /// </summary>
    public class RhombWidget : ShapeWidget, ICanSameSize, ICanBeLinkedWidget, ITextRotate
    {
        #region 构造方法=====================================================================================================

        /// <summary>
        /// [静态构造方法]
        /// </summary>
        static RhombWidget()
        {
            dashArray = new DoubleCollection() { 2, 2 };
        }

        /// <summary>
        /// [构造方法]
        /// </summary>
        /// <param name="pageEditor"></param>
        public RhombWidget(PageEditorReader editor)
            : base(editor)
        {
            widgetType = Enums.WidgetTypes.Rhomb;
            widgetClassLocalName = Widget.GetWidgetClassLocalName(this.GetType().Name);

            mainPolyLine.Fill = null;
            mainPolyLine.Stroke = WidgetForeColor;

            this.mainCanvas.Children.Add(mainPolyLine);

            Canvas.SetZIndex(mainPolyLine, 0);
            
            this.commentAdorner = new CommentAdorner(this.mainPolyLine, this) { Visibility = System.Windows.Visibility.Collapsed };//默认不显示。

            this.hyperLinkAdorner = new HyperLinkAdorner(this.mainPolyLine, this) { Visibility = Visibility.Collapsed };
            this.hyperLinkAdorner.MouseLeftButtonUp += new MouseButtonEventHandler(hyperLinkAdorner_MouseLeftButtonUp);

            AdornerLayer adornerLayer = AdornerLayer.GetAdornerLayer(this.mainCanvas);
            if (adornerLayer == null)
            {
                MessageBox.Show("　　未找到Widget的装饰层！", Globals.AppName, MessageBoxButton.OK, MessageBoxImage.Warning);
            }
            else
            {
                adornerLayer.Add(this.commentAdorner);//这个要在各具体部件类中添加。
                adornerLayer.Add(this.hyperLinkAdorner);//这个要在各具体部件类中添加。
            }

            //最后添加文本面板。
            this.mainCanvas.Children.Add(this.mainTextPanel);
            Canvas.SetZIndex(this.mainTextPanel, 2);
        }

        #endregion


        #region 字段与属性===================================================================================================

        public override Point BottomRight
        {
            get
            {
                double minLeft, minTop, maxRight, maxBottom;

                minLeft = Math.Min(startPoint.X, endPoint.X);
                maxRight = Math.Max(startPoint.X, endPoint.X);

                minTop = Math.Min(startPoint.Y, endPoint.Y);
                maxBottom = Math.Max(startPoint.Y, endPoint.Y);

                return new Point(maxRight, maxBottom);
            }
        }

        /// <summary>
        /// 点划线定义。
        /// </summary>
        private static DoubleCollection dashArray;
        
        private Point EndBasePoint
        {
            get
            {
                return new Point(Math.Max(startPoint.X, endPoint.X), Math.Max(startPoint.Y, endPoint.Y));
            }
        }
        
        private Point endPoint = new Point();
        /// <summary>
        /// [读写]终点。
        /// </summary>
        [Tools.LunarProperty("EndPoint", PropertyDateType.Point)]
        public Point EndPoint
        {
            get { return endPoint; }
            set
            {
                endPoint = value;
                if (this.xmlData != null)
                {
                    this.xmlData.SetAttribute(XmlTags.EndPointTag, value.ToString());
                }

                RefreshLocation();
            }
        }

        /// <summary>
        /// [只读]表示当前部件是否被某个连接线挂接着。
        /// </summary>
        public bool IsLinked
        {
            get
            {
                if (this.masterEditor == null) return false;

                foreach (UIElement ue in this.masterEditor.Children)
                {
                    ILinkableLine linkedLine = ue as ILinkableLine;
                    if (linkedLine == null) continue;

                    if (linkedLine.StartMasterId == this.id || linkedLine.EndMasterId == this.id) return true;
                }

                return false;
            }
        }

        private Polygon mainPolyLine = new Polygon()
        {
            Cursor = Cursors.Hand,
            StrokeLineJoin = PenLineJoin.Round,
        };

        private Rect movingRect;
        /// <summary>
        /// 部件正在被拖动时的外边框。
        /// </summary>
        public Rect MovingRect
        {
            get
            {
                return movingRect;
            }
        }

        private Point StartBasePoint
        {
            get
            {
                return new Point(Math.Min(startPoint.X, endPoint.X), Math.Min(startPoint.Y, endPoint.Y));
            }
        }
        
        private Point startPoint = new Point();
        /// <summary>
        /// [读写]起点。
        /// </summary>
        [Tools.LunarProperty("StartPoint", PropertyDateType.Point)]
        public Point StartPoint
        {
            get { return startPoint; }
            set
            {
                startPoint = value;
                if (this.xmlData != null)
                {
                    this.xmlData.SetAttribute(XmlTags.StartPointTag, value.ToString());
                }

                RefreshLocation();
            }
        }

        private double textRotateAngle = 0;
        /// <summary>
        /// [读写]文本旋转角度。取值范围：[-180,180]。
        /// </summary>
        [Tools.LunarProperty("TextRotateAngle", PropertyDateType.Double)]
        public double TextRotateAngle
        {
            get { return textRotateAngle; }
            set
            {
                if (value > 180)
                {
                    textRotateAngle = 180;
                }
                else if (value < -180)
                {
                    textRotateAngle = -180;
                }
                else
                {
                    textRotateAngle = value;
                }

                if (this.xmlData != null)
                {
                    this.xmlData.SetAttribute(XmlTags.TextRotateAngleTag, textRotateAngle.ToString());
                }

                this.RefreshTextRotateAngle();
            }
        }

        public override Point TopLeft
        {
            get
            {
                double minLeft, minTop, maxRight, maxBottom;

                minLeft = Math.Min(startPoint.X, endPoint.X);
                maxRight = Math.Max(startPoint.X, endPoint.X);

                minTop = Math.Min(startPoint.Y, endPoint.Y);
                maxBottom = Math.Max(startPoint.Y, endPoint.Y);

                return new Point(minLeft, minTop);
            }
        }

        private Enums.WidgetForm widgetForm = Enums.WidgetForm.Rhomb;//默认
        /// <summary>
        /// [读写]部件形态。默认值是Rhomb。
        /// </summary>
        [Tools.LunarProperty("WidgetForm", PropertyDateType.WidgetForm)]
        public Enums.WidgetForm WidgetForm
        {
            get { return widgetForm; }
            set
            {
                widgetForm = value;
                if (this.xmlData != null)
                {
                    this.xmlData.SetAttribute(XmlTags.WidgetFormTag, value.ToString());
                }
                this.DrawLine();
            }
        }


        #endregion


        #region 方法=========================================================================================================

        /// <summary>
        /// 根据XmlData的信息，生成部件内容，设置部件格式。
        /// </summary>
        public override void Build()
        {
            base.Build();

            if (this.xmlData == null) return;

            XmlAttribute attrStartPoint = this.xmlData.GetAttribute(XmlTags.StartPointTag);
            if (attrStartPoint != null)
            {
                this.startPoint = Point.Parse(attrStartPoint.Value);
            }

            XmlAttribute attrEndPoint = this.xmlData.GetAttribute(XmlTags.EndPointTag);
            if (attrEndPoint != null)
            {
                this.endPoint = Point.Parse(attrEndPoint.Value);
            }

            XmlAttribute attrTextRotateAngle = this.xmlData.GetAttribute(XmlTags.TextRotateAngleTag);
            if (attrTextRotateAngle != null)
            {
                this.textRotateAngle = double.Parse(attrTextRotateAngle.Value);
            }

            XmlAttribute attrWidgetForm = this.xmlData.GetAttribute(XmlTags.WidgetFormTag);
            if (attrWidgetForm != null)
            {
                this.widgetForm = (Enums.WidgetForm)Enum.Parse(typeof(Enums.WidgetForm), attrWidgetForm.Value);
            }

            this.RefreshTextRotateAngle();
            this.RefreshLocation();

            //此类是下面这几个属性的“最终实现类”。这些属性的值都已在基类确定。因此调用,
            this.RefreshWidgetBackColor();
            this.RefreshWidgetLineColor();
            this.RefreshWidgetLineWidth();
            this.RefreshLineDash();
        }
        
        public void DrawLine()
        {
            if (masterEditor == null) return;

            DrawLine(this.startPoint, this.endPoint, false);
        }

        /// <summary>
        /// 菱形由两个端点足以决定。
        /// </summary>
        /// <param name="startPoint">首端点。</param>
        /// <param name="endPoint">尾端点。</param>
        /// <param name="isShift">是否按住Shift键。</param>
        private void DrawLine(Point startPoint, Point endPoint, bool isShift)
        {
            Point startBasePt, endBasePt;

            startBasePt = new Point(Math.Min(startPoint.X, endPoint.X),
                   Math.Min(startPoint.Y, endPoint.Y));
            endBasePt = new Point(Math.Max(startPoint.X, endPoint.X),
              Math.Max(startPoint.Y, endPoint.Y));

            if (isShift)
            {
                if (startPoint.Y > endPoint.Y)
                {
                    endBasePt.Y = startBasePt.Y + (endBasePt.X - startBasePt.X);
                }
                else
                {
                    startBasePt.Y = endBasePt.Y - (endBasePt.X - startBasePt.X);
                }
            }

            startBasePt = FormatPoint(startBasePt);
            endBasePt = FormatPoint(endBasePt);

            switch (this.widgetForm)
            {
                case Enums.WidgetForm.Cross:
                    {
                        DrawCross(ref startBasePt, ref endBasePt);
                        break;
                    }
                case Enums.WidgetForm.SixSideShape:
                    {
                        DrawSixSideShape(ref startBasePt, ref endBasePt);
                        break;
                    }
                case Enums.WidgetForm.EightSidedShape:
                    {
                        DrawEightSideShape(ref startBasePt, ref endBasePt);
                        break;
                    }
                case Enums.WidgetForm.LeftParallelogram:
                    {
                        DrawLeftParallelogram(ref startBasePt, ref endBasePt);
                        break;
                    }
                case Enums.WidgetForm.RightParallelogram:
                    {
                        DrawRightParallelogram(ref startBasePt, ref endBasePt);
                        break;
                    }
                case Enums.WidgetForm.LeftFillArrow:
                case Enums.WidgetForm.LeftFletchingArrow:
                case Enums.WidgetForm.LeftTailArrow:
                    {
                        DrawLeftArrow(ref startBasePt, ref endBasePt, this.widgetForm);
                        break;
                    }
                case Enums.WidgetForm.RightFillArrow:
                case Enums.WidgetForm.RightFletchingArrow:
                case Enums.WidgetForm.RightTailArrow:
                    {
                        DrawRightArrow(ref startBasePt, ref endBasePt, this.widgetForm);
                        break;
                    }
                case Enums.WidgetForm.TopFillArrow:
                case Enums.WidgetForm.TopFletchingArrow:
                case Enums.WidgetForm.TopTailArrow:
                    {
                        DrawTopArrow(ref startBasePt, ref endBasePt, this.widgetForm);
                        break;
                    }
                case Enums.WidgetForm.BottomFillArrow:
                case Enums.WidgetForm.BottomFletchingArrow:
                case Enums.WidgetForm.BottomTailArrow:
                    {
                        DrawBottomArrow(ref startBasePt, ref endBasePt, this.widgetForm);
                        break;
                    }
                case Enums.WidgetForm.Star:
                    {
                        DrawStar(ref startBasePt, ref endBasePt); break;
                    }
                default:
                    {
                        DrawRhomb(ref startBasePt, ref endBasePt);
                        break;
                    }
            }
            //this.centerAdorner.InvalidateVisual();//移动过程中无需刷新装饰器。

            //移动部件控制点时，要刷新连接线的。
            this.movingRect = new Rect(startBasePt, endBasePt);

            LocateTextPanel(startBasePt, endBasePt);
            
        }

        /// <summary>
        /// 绘制形态。
        /// </summary>
        private void DrawStar(ref Point startBasePt, ref Point endBasePt)
        {
            Point p1, p2, p3, p4, p5, p6, p7, p8;

            double halfWidth = Math.Abs(endBasePt.X - startBasePt.X) / 2;
            double halfHeight = Math.Abs(endBasePt.Y - startBasePt.Y) / 2;

            Point center = new Point(startBasePt.X + halfWidth, startBasePt.Y + halfHeight);

            double xOffset = Math.Abs((int)(halfWidth / 4));
            double yOffset = Math.Abs((int)(halfHeight / 4));

            p1 = new Point(center.X - xOffset, center.Y - yOffset);
            p2 = new Point(center.X, startBasePt.Y);
            p3 = new Point(center.X + xOffset, p1.Y);
            p4 = new Point(endBasePt.X, center.Y);
            p5 = new Point(p3.X, center.Y + yOffset);
            p6 = new Point(p2.X, endBasePt.Y);
            p7 = new Point(p1.X, p5.Y);
            p8 = new Point(startBasePt.X, center.Y);

            mainPolyLine.Points = new PointCollection()
            {
                p1,p2,p3,p4,p5,p6,p7,p8,
            };
        }

        /// <summary>
        /// 绘制形态。
        /// </summary>
        private void DrawBottomArrow(ref Point startBasePt, ref Point endBasePt, WidgetForm widgetForm)
        {
            Point p1, p2, p3, p4;

            double width = Math.Abs(endBasePt.X - startBasePt.X);
            double offset = Math.Abs((int)(width / 2 / Math.Sqrt(3)));

            if (offset > Math.Abs(endBasePt.Y - startBasePt.Y))
            {
                //如果纵向偏移量过大，则画成矩形
                p1 = startBasePt;
                p2 = new Point(endBasePt.X, startBasePt.Y);
                p3 = endBasePt;
                p4 = new Point(startBasePt.X, endBasePt.Y);

                mainPolyLine.Points = new PointCollection()
                {
                    p1,p2,p3,p4,
                };
            }
            else
            {
                Point p5, p6;

                p1 = startBasePt;
                p2 = new Point(startBasePt.X + width / 2, startBasePt.Y + offset);
                p3 = new Point(endBasePt.X, startBasePt.Y);
                p4 = new Point(p3.X, endBasePt.Y - offset);
                p5 = new Point(p2.X, endBasePt.Y);
                p6 = new Point(startBasePt.X, p4.Y);

                switch (widgetForm)
                {
                    case Enums.WidgetForm.BottomFillArrow:
                        {
                            mainPolyLine.Points = new PointCollection()
                            {
                                p1,/*p2,*/p3,p4,p5,p6//就少个p2,
                            };
                            break;
                        }
                    case Enums.WidgetForm.BottomFletchingArrow:
                        {
                            mainPolyLine.Points = new PointCollection()
                            {
                                p1,p2,p3,p4,p5,p6,
                            };
                            break;
                        }
                    case Enums.WidgetForm.BottomTailArrow:
                        {
                            mainPolyLine.Points = new PointCollection()
                            {
                                p1,p2,p3,p5,
                            };
                            break;
                        }
                }
            }
        }

        /// <summary>
        /// 绘制形态。
        /// </summary>
        private void DrawTopArrow(ref Point startBasePt, ref Point endBasePt, WidgetForm widgetForm)
        {
            Point p1, p2, p3, p4;

            double width = Math.Abs(endBasePt.X - startBasePt.X);
            double offset = Math.Abs((int)(width / 2 / Math.Sqrt(3)));

            if (offset > Math.Abs(endBasePt.Y - startBasePt.Y))
            {
                //如果纵向偏移量过大，则画成矩形
                p1 = startBasePt;
                p2 = new Point(endBasePt.X, startBasePt.Y);
                p3 = endBasePt;
                p4 = new Point(startBasePt.X, endBasePt.Y);

                mainPolyLine.Points = new PointCollection()
                {
                    p1,p2,p3,p4,
                };
            }
            else
            {
                Point p5, p6;

                p1 = new Point(startBasePt.X + width / 2, startBasePt.Y);
                p2 = new Point(endBasePt.X, startBasePt.Y + offset);
                p3 = endBasePt;
                p4 = new Point(p1.X, endBasePt.Y - offset);
                p5 = new Point(startBasePt.X, endBasePt.Y);
                p6 = new Point(startBasePt.X, p2.Y);

                switch (widgetForm)
                {
                    case Enums.WidgetForm.TopFillArrow:
                        {
                            mainPolyLine.Points = new PointCollection()
                            {
                                p1,p2,p3,/*p4,*/p5,p6//就少个p4,
                            };
                            break;
                        }
                    case Enums.WidgetForm.TopFletchingArrow:
                        {
                            mainPolyLine.Points = new PointCollection()
                            {
                                p1,p2,p3,p4,p5,p6,
                            };
                            break;
                        }
                    case Enums.WidgetForm.TopTailArrow:
                        {
                            mainPolyLine.Points = new PointCollection()
                            {
                                p1,p3,p4,p5,
                            };
                            break;
                        }
                }
            }
        }

        /// <summary>
        /// 绘制形态。
        /// </summary>
        private void DrawLeftArrow(ref Point startBasePt, ref Point endBasePt, WidgetForm widgetForm)
        {
            Point p1, p2, p3, p4;

            double height = Math.Abs(endBasePt.Y - startBasePt.Y);
            double offset = Math.Abs((int)(height / 2 / Math.Sqrt(3)));

            if (offset > Math.Abs(endBasePt.X - startBasePt.X))
            {
                //如果横向偏移量过大，则画成矩形
                p1 = startBasePt;
                p2 = new Point(endBasePt.X, startBasePt.Y);
                p3 = endBasePt;
                p4 = new Point(startBasePt.X, endBasePt.Y);

                mainPolyLine.Points = new PointCollection()
                {
                    p1,p2,p3,p4,
                };
            }
            else
            {
                Point p5, p6;

                p1 = new Point(startBasePt.X + offset, startBasePt.Y);
                p2 = new Point(endBasePt.X, startBasePt.Y);
                p3 = new Point(endBasePt.X - offset, startBasePt.Y + height / 2);
                p4 = endBasePt;
                p5 = new Point(p1.X, endBasePt.Y);
                p6 = new Point(startBasePt.X, p3.Y);

                switch (widgetForm)
                {
                    case Enums.WidgetForm.LeftFillArrow:
                        {
                            mainPolyLine.Points = new PointCollection()
                            {
                                p1,p2,/*p3,*/p4,p5,p6//就少个p3,
                            };
                            break;
                        }
                    case Enums.WidgetForm.LeftFletchingArrow:
                        {
                            mainPolyLine.Points = new PointCollection()
                            {
                                p1,p2,p3,p4,p5,p6,
                            };
                            break;
                        }
                    case Enums.WidgetForm.LeftTailArrow:
                        {
                            mainPolyLine.Points = new PointCollection()
                            {
                                p2,p3,p4,p6,
                            };
                            break;
                        }
                }
            }
        }

        /// <summary>
        /// 绘制形态。
        /// </summary>
        private void DrawRightArrow(ref Point startBasePt, ref Point endBasePt, WidgetForm widgetForm)
        {
            Point p1, p2, p3, p4;

            double height = Math.Abs(endBasePt.Y - startBasePt.Y);
            double offset = Math.Abs((int)(height / 2 / Math.Sqrt(3)));

            if (offset > Math.Abs(endBasePt.X - startBasePt.X))
            {
                //如果横向偏移量过大，则画成矩形
                p1 = startBasePt;
                p2 = new Point(endBasePt.X, startBasePt.Y);
                p3 = endBasePt;
                p4 = new Point(startBasePt.X, endBasePt.Y);

                mainPolyLine.Points = new PointCollection()
                {
                    p1,p2,p3,p4,
                };
            }
            else
            {
                Point p5, p6;

                p1 = startBasePt;
                p2 = new Point(endBasePt.X - offset, startBasePt.Y);
                p3 = new Point(endBasePt.X, startBasePt.Y + height / 2);
                p4 = new Point(p2.X, endBasePt.Y);
                p5 = new Point(p1.X, endBasePt.Y);
                p6 = new Point(startBasePt.X + offset, p3.Y);


                switch (widgetForm)
                {
                    case Enums.WidgetForm.RightFillArrow:
                        {
                            mainPolyLine.Points = new PointCollection()
                            {
                                p1,p2,p3,p4,p5,//p6//就少个p6,
                            };
                            break;
                        }
                    case Enums.WidgetForm.RightFletchingArrow:
                        {
                            mainPolyLine.Points = new PointCollection()
                            {
                                p1,p2,p3,p4,p5,p6,
                            };
                            break;
                        }
                    case Enums.WidgetForm.RightTailArrow:
                        {
                            mainPolyLine.Points = new PointCollection()
                            {
                                p1,p3,p5,p6,
                            };
                            break;
                        }
                }
            }
        }

        /// <summary>
        /// 绘制形态。
        /// </summary>
        private void DrawRhomb(ref Point startBasePt, ref Point endBasePt)
        {
            Point p1, p2, p3, p4;
            p1 = new Point(startBasePt.X, startBasePt.Y + (endBasePt.Y - startBasePt.Y) / 2);
            p2 = new Point(startBasePt.X + (endBasePt.X - startBasePt.X) / 2, startBasePt.Y);
            p3 = new Point(endBasePt.X, p1.Y);
            p4 = new Point(p2.X, endBasePt.Y);
            mainPolyLine.Points = new PointCollection()
            {
                p1,p2,p3,p4,
            };
        }

        /// <summary>
        /// 绘制形态。
        /// </summary>
        private void DrawRightParallelogram(ref Point startBasePt, ref Point endBasePt)
        {
            Point p1, p2, p3, p4;

            double height = Math.Abs(endBasePt.Y - startBasePt.Y);
            double hoffset = height / Math.Sqrt(3);

            if (hoffset > Math.Abs(endBasePt.X - startBasePt.X))
            {
                //如果横向偏移量过大，则画成矩形
                p1 = startBasePt;
                p2 = new Point(endBasePt.X, startBasePt.Y);
                p3 = endBasePt;
                p4 = new Point(startBasePt.X, endBasePt.Y);
            }
            else
            {
                p1 = startBasePt;
                p2 = new Point(endBasePt.X - hoffset, startBasePt.Y);
                p3 = endBasePt;
                p4 = new Point(startBasePt.X + hoffset, endBasePt.Y);
            }

            mainPolyLine.Points = new PointCollection()
                        {
                            p1,p2,p3,p4,
                        };
        }

        /// <summary>
        /// 绘制形态。
        /// </summary>
        private void DrawLeftParallelogram(ref Point startBasePt, ref Point endBasePt)
        {
            Point p1, p2, p3, p4;

            double height = Math.Abs(endBasePt.Y - startBasePt.Y);
            double hoffset = height / Math.Sqrt(3);

            if (hoffset > Math.Abs(endBasePt.X - startBasePt.X))
            {
                //如果横向偏移量过大，则画成矩形
                p1 = startBasePt;
                p2 = new Point(endBasePt.X, startBasePt.Y);
                p3 = endBasePt;
                p4 = new Point(startBasePt.X, endBasePt.Y);
            }
            else
            {
                p1 = new Point(startBasePt.X + hoffset, startBasePt.Y);
                p2 = new Point(endBasePt.X, startBasePt.Y);
                p3 = new Point(endBasePt.X - hoffset, endBasePt.Y);
                p4 = new Point(startBasePt.X, endBasePt.Y);
            }

            mainPolyLine.Points = new PointCollection()
                        {
                            p1,p2,p3,p4,
                        };
        }

        /// <summary>
        /// 绘制“Cross”形态。
        /// </summary>
        /// <param name="startBasePt"></param>
        /// <param name="endBasePt"></param>
        private void DrawCross(ref Point startBasePt, ref Point endBasePt)
        {
            Point p1, p2, p3, p4;

            double height = Math.Abs(endBasePt.Y - startBasePt.Y);
            double offset = (int)(height / (2 + Math.Sqrt(2)));

            if (offset * 2 > Math.Abs(endBasePt.X - startBasePt.X))
            {
                //如果横向偏移量过大，则画成矩形
                p1 = startBasePt;
                p2 = new Point(endBasePt.X, startBasePt.Y);
                p3 = endBasePt;
                p4 = new Point(startBasePt.X, endBasePt.Y);

                mainPolyLine.Points = new PointCollection()
                            {
                                p1,p2,p3,p4,
                            };
            }
            else
            {
                Point p5, p6, p7, p8;
                Point pTR, pBR, pBL, pTL;
                p1 = new Point(startBasePt.X + offset, startBasePt.Y);
                p2 = new Point(endBasePt.X - offset, startBasePt.Y);
                p3 = new Point(endBasePt.X, startBasePt.Y + offset);
                pTR = new Point(p2.X, p3.Y);

                p4 = new Point(endBasePt.X, endBasePt.Y - offset);
                p5 = new Point(p2.X, endBasePt.Y);
                pBR = new Point(p5.X, p4.Y);

                p6 = new Point(p1.X, endBasePt.Y);
                p7 = new Point(startBasePt.X, p4.Y);
                pBL = new Point(p6.X, p7.Y);

                p8 = new Point(startBasePt.X, p3.Y);
                pTL = new Point(p1.X, p8.Y);

                mainPolyLine.Points = new PointCollection()
                            {
                                p1,p2,pTR,p3,p4,pBR,p5,p6,pBL,p7,p8,pTL,
                            };
            }
        }

        /// <summary>
        /// 绘制“SixSideShape”形态。
        /// </summary>
        /// <param name="startBasePt"></param>
        /// <param name="endBasePt"></param>
        private void DrawSixSideShape(ref Point startBasePt, ref Point endBasePt)
        {
            Point p1, p2, p3, p4;

            double height = Math.Abs(endBasePt.Y - startBasePt.Y);
            double offset = Math.Abs((int)(height / 2 / Math.Sqrt(3)));

            if (offset * 2 > Math.Abs(endBasePt.X - startBasePt.X))
            {
                //如果横向偏移量过大，则画成矩形
                p1 = startBasePt;
                p2 = new Point(endBasePt.X, startBasePt.Y);
                p3 = endBasePt;
                p4 = new Point(startBasePt.X, endBasePt.Y);

                mainPolyLine.Points = new PointCollection()
                {
                    p1,p2,p3,p4,
                };
            }
            else
            {
                Point p5, p6;

                p1 = new Point(startBasePt.X + offset, startBasePt.Y);
                p2 = new Point(endBasePt.X - offset, startBasePt.Y);
                p3 = new Point(endBasePt.X, startBasePt.Y + height / 2);
                p4 = new Point(p2.X, endBasePt.Y);
                p5 = new Point(p1.X, endBasePt.Y);
                p6 = new Point(startBasePt.X, p3.Y);

                mainPolyLine.Points = new PointCollection()
                {
                    p1,p2,p3,p4,p5,p6,
                };
            }
        }

        /// <summary>
        /// 绘制“EightSideShape”形态。
        /// </summary>
        /// <param name="startBasePt"></param>
        /// <param name="endBasePt"></param>
        private void DrawEightSideShape(ref Point startBasePt, ref Point endBasePt)
        {
            Point p1, p2, p3, p4;

            double height = Math.Abs(endBasePt.Y - startBasePt.Y);
            double offset = (int)(height / (2 + Math.Sqrt(2)));

            if (offset * 2 > Math.Abs(endBasePt.X - startBasePt.X))
            {
                //如果横向偏移量过大，则画成矩形
                p1 = startBasePt;
                p2 = new Point(endBasePt.X, startBasePt.Y);
                p3 = endBasePt;
                p4 = new Point(startBasePt.X, endBasePt.Y);

                mainPolyLine.Points = new PointCollection()
                {
                    p1,p2,p3,p4,
                };
            }
            else
            {
                Point p5, p6, p7, p8;
                p1 = new Point(startBasePt.X + offset, startBasePt.Y);
                p2 = new Point(endBasePt.X - offset, startBasePt.Y);
                p3 = new Point(endBasePt.X, startBasePt.Y + offset);
                p4 = new Point(endBasePt.X, endBasePt.Y - offset);
                p5 = new Point(p2.X, endBasePt.Y);
                p6 = new Point(p1.X, endBasePt.Y);
                p7 = new Point(startBasePt.X, p4.Y);
                p8 = new Point(startBasePt.X, p3.Y);

                mainPolyLine.Points = new PointCollection()
                {
                    p1,p2,p3,p4,p5,p6,p7,p8,
                };
            }
        }

        /// <summary>
        /// 重定文本位置。
        /// </summary>
        /// <param name="startPoint">首基准点。</param>
        /// <param name="endPoint">尾基准点。</param>
        private void LocateTextPanel(Point startBasePt, Point endBasePt)
        {
            Point center = new Point(startBasePt.X + (endBasePt.X - startBasePt.X) / 2,
                startBasePt.Y + (endBasePt.Y - startBasePt.Y) / 2);

            Point textStart = new Point(center.X - this.mainTextPanel.ActualWidth / 2 - this.mainTextPanel.Margin.Left,
                center.Y - this.mainTextPanel.ActualHeight / 2 - this.mainTextPanel.Margin.Top);

            Canvas.SetLeft(this.mainTextPanel, textStart.X);
            Canvas.SetTop(this.mainTextPanel, textStart.Y);
        }

        /// <summary>
        /// 这个虚方法是用以查看本部件是否在选定框的内部。
        /// 线型部件，各有各的计算办法。
        /// </summary>
        /// <param name="rect"></param>
        /// <returns></returns>
        public override bool IsInRect(Rect rect)
        {
            //return base.IsInRect(rect);//这个要屏蔽。
            bool isInRect = base.IsInRect(rect);
            if (isInRect)
            {
                return true;
            }
            else
            {
                Rect virtualRect = new Rect(startPoint, endPoint);
                return rect.IntersectsWith(virtualRect);
            }
        }

        /// <summary>
        /// 取与自身挂接的连接线。
        /// </summary>
        /// <returns>可能返回null。</returns>
        public List<ILinkableLine> GetLinkedLines()
        {
            if (this.masterEditor == null) return null;

            List<Widget> widgets = new List<Widget>();
            widgets.Add(this);

            return this.masterEditor.GetLinkedLines(widgets);
        }

        public override string GetRelativeOuterXml(Point baseCopyTopLeft)
        {
            if (this.xmlData == null) return string.Empty;

            Point oldStartPoint = startPoint;
            Point newStartPoint = new Point(oldStartPoint.X - baseCopyTopLeft.X,
                oldStartPoint.Y - baseCopyTopLeft.Y);
            this.xmlData.SetAttribute(XmlTags.StartPointTag, newStartPoint.ToString());

            Point oldEndPoint = endPoint;
            Point newEndPoint = new Point(oldEndPoint.X - baseCopyTopLeft.X,
                oldEndPoint.Y - baseCopyTopLeft.Y);
            this.xmlData.SetAttribute(XmlTags.EndPointTag, newEndPoint.ToString());

            System.Text.StringBuilder sb = new System.Text.StringBuilder();
            sb.Append(this.xmlData.OuterXml);

            this.xmlData.SetAttribute(XmlTags.StartPointTag, oldStartPoint.ToString());
            this.xmlData.SetAttribute(XmlTags.EndPointTag, oldEndPoint.ToString());

            return sb.ToString();
        }
        
        public override void RefreshLineDash()
        {
            switch (lineDash)
            {
                case LineDashType.DashType.Dash:
                    {
                        this.mainPolyLine.StrokeDashArray = LineDashType.dashCollection; break;
                    }
                case LineDashType.DashType.DashDotDot:
                    {
                        this.mainPolyLine.StrokeDashArray = LineDashType.dashDotDotCollection; break;
                    }
                case LineDashType.DashType.Dot:
                    {
                        this.mainPolyLine.StrokeDashArray = LineDashType.dotCollection; break;
                    }
                case LineDashType.DashType.Solid:
                    {
                        this.mainPolyLine.StrokeDashArray = LineDashType.solidCollection; break;
                    }
                default:
                    {
                        this.mainPolyLine.StrokeDashArray = LineDashType.dashDotCollection; break;
                    }
            }
        }

        public override void RefreshWidgetLineWidth()
        {
            mainPolyLine.StrokeThickness = widgetLineWidth;
        }

        public override void RefreshLocation()
        {
            base.RefreshLocation();

            DrawLine();

            //Point p1, p2, p3, p4;

            //p1 = new Point(startPoint.X, startPoint.Y + (endPoint.Y - startPoint.Y) / 2);
            //p2 = new Point(startPoint.X + (endPoint.X - startPoint.X) / 2, startPoint.Y);
            //p3 = new Point(endPoint.X, p1.Y);
            //p4 = new Point(p2.X, endPoint.Y);

            //mainPolyLine.Points = new PointCollection(){
            //    p1,p2,p3,p4,
            //};

            //this.movingRect = new Rect(startPoint, endPoint);

            RefreshWidgetLineWidth();
            this.RefreshTextRotateAngle();
            
            this.commentAdorner.InvalidateVisual();
        }

        public override void RefreshPointWhenGroupIn(Point baseTopLeft)
        {
            Point oldStartPoint = startPoint;
            Point newStartPoint = new Point(oldStartPoint.X - baseTopLeft.X,
                oldStartPoint.Y - baseTopLeft.Y);
            StartPoint = newStartPoint;

            Point oldEndPoint = endPoint;
            Point newEndPoint = new Point(oldEndPoint.X - baseTopLeft.X,
                oldEndPoint.Y - baseTopLeft.Y);
            EndPoint = newEndPoint;
        }

        public override void RefreshPointWhenGroupOut(Point baseTopLeft)
        {
            Point oldStartPoint = startPoint;
            Point newStartPoint = new Point(oldStartPoint.X + baseTopLeft.X,
                oldStartPoint.Y + baseTopLeft.Y);
            StartPoint = newStartPoint;

            Point oldEndPoint = endPoint;
            Point newEndPoint = new Point(oldEndPoint.X + baseTopLeft.X,
                oldEndPoint.Y + baseTopLeft.Y);
            EndPoint = newEndPoint;
        }

        public override void RefreshIsShadowVisible()
        {
            //base.RefreshIsShadowVisible();//保持文本清晰

            if (isShadowVisible)
            {
                this.mainPolyLine.Effect = Widget.ShadowEffect;
            }
            else
            {
                this.mainPolyLine.Effect = null;
            }
        }

        public override void RefreshTextPanelLocatin()
        {
            Point center = new Point(this.startPoint.X + (this.endPoint.X - this.startPoint.X) / 2,
                this.startPoint.Y + (this.endPoint.Y - this.startPoint.Y) / 2);

            Point textStart = new Point(center.X - this.mainTextPanel.ActualWidth / 2 - this.mainTextPanel.Margin.Left,
                center.Y - this.mainTextPanel.ActualHeight / 2 - this.mainTextPanel.Margin.Top);

            Canvas.SetLeft(this.mainTextPanel, textStart.X);
            Canvas.SetTop(this.mainTextPanel, textStart.Y);
        }

        public override void RefreshWidgetBackColor()
        {
            base.RefreshWidgetBackColor();
            if (widgetBackColor == Brushes.Transparent)
            {
                this.mainPolyLine.Fill = null;
            }
            else
            {
                this.mainPolyLine.Fill = widgetBackColor;
            }
        }

        public override void RefreshWidgetLineColor()
        {
            this.mainPolyLine.Stroke = widgetLineColor;
        }

        /// <summary>
        /// 刷新文本区旋转角度。
        /// </summary>
        public void RefreshTextRotateAngle()
        {
            if (this.mainTextPanel.RenderTransformOrigin != DefaultRenderCenter)
            {
                this.mainTextPanel.RenderTransformOrigin = DefaultRenderCenter;
            }

            if (this.textRotateAngle == 0)
            {
                this.mainTextPanel.RenderTransform = DefaultRotateTransform;
            }
            else
            {
                this.mainTextPanel.RenderTransform = new RotateTransform(textRotateAngle);
            }
        }

        #endregion


    }
}
